﻿using System;
using System.Net;
using System.Windows;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Silverlight.Testing;
using System.Windows.Data;

namespace ThemeLoader.Test.Integration
{

    [TestClass]
    public class ThemeManagerTests : SilverlightTest
    {
        private ThemeManager themeManager;
        private ThemeLoader themeLoader;

        [TestInitialize]
        public void SetUpTest()
        {
            var resourceProvider = new DelegateResourceProvider(() => Application.Current.Resources);
            themeManager = new ThemeManager(resourceProvider, () => { });
            themeLoader = new ThemeLoader();
        }

        [TestMethod]
        [Asynchronous]
        public void ApplyTheme_NoThemeApplied_ThemeIsExchanged()
        {
            RunThemeTest((theme1, theme2) =>
            {
                themeManager.ApplyTheme(theme1);
                Style style = (Style)Application.Current.Resources["buttonStyle"];
                AssertBackgroundColorEquals(Colors.Yellow, style);
            });
        }

        [TestMethod]
        [Asynchronous]
        public void ApplyTheme_OneThemeApplied_ThemeIsExchanged()
        {
            RunThemeTest((theme1, theme2) =>
                {
                    themeManager.ApplyTheme(theme1);
                    Style style = (Style)Application.Current.Resources["buttonStyle"];
                    AssertBackgroundColorEquals(Colors.Yellow, style);

                    themeManager.ApplyTheme(theme2);
                    style = (Style)Application.Current.Resources["buttonStyle"];
                    AssertBackgroundColorEquals(Colors.Blue, style);
                });
        }

        [TestMethod]
        [Asynchronous]
        public void ApplyTheme_TwoThemeConsecutivelyApplied_ThemeIsExchanged()
        {
            RunThemeTest((theme1, theme2) =>
            {
                themeManager.ApplyTheme(theme1);
                Style style = (Style)Application.Current.Resources["buttonStyle"];
                AssertBackgroundColorEquals(Colors.Yellow, style);

                themeManager.ApplyTheme(theme2);
                style = (Style)Application.Current.Resources["buttonStyle"];
                AssertBackgroundColorEquals(Colors.Blue, style);

                themeManager.ApplyTheme(theme1);
                style = (Style)Application.Current.Resources["buttonStyle"];
                AssertBackgroundColorEquals(Colors.Yellow, style);
            });
        }

        private void RunThemeTest(Action<ResourceDictionary, ResourceDictionary> test)
        {
            ResourceDictionary theme1 = null;
            ResourceDictionary theme2 = null;

            themeLoader.DownloadTheme("CompressedThemes/theme1.zip", "theme1.xaml", e =>
            {
                theme1 = e.Result;
            });

            themeLoader.DownloadTheme("CompressedThemes/theme2.zip", "theme2.xaml", e =>
            {
                theme2 = e.Result;
            });

            base.EnqueueConditional(() => theme1 != null);
            base.EnqueueConditional(() => theme2 != null);

            base.EnqueueCallback(() =>
            {
                test(theme1, theme2);
                EnqueueTestComplete();
            });
        }

        private void AssertBackgroundColorEquals(Color expected, Style style)
        {
            var color = GetBackgroundColor(style);
            Assert.Equals(expected, color);
        }

        private Color GetBackgroundColor(Style style)
        {
            var backgroundSetter = style.Setters.OfType<Setter>()
                                                .FirstOrDefault(setter => setter.Property == Button.BackgroundProperty);

            var brush = (SolidColorBrush)backgroundSetter.Value;

            return brush.Color;
        }
    }
}
